package jmine.tec.hydra;

import java.io.InputStream;
import java.util.Map;

import javax.naming.Context;

import jmine.tec.executionlog.ExecutionLogController;
import jmine.tec.hydra.api.Hydra;
import jmine.tec.hydra.api.HydraProvider;
import jmine.tec.hydra.api.HydraRequest;
import jmine.tec.hydra.api.HydraSpecification;
import jmine.tec.hydra.domain.HydraSystem;
import jmine.tec.hydra.domain.enumx.HydraUniqueValueEnum;
import jmine.tec.script.persistent.ScriptController;
import jmine.tec.services.ServicesController;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

import bancosys.tec.persist.PersistenceController;
import bancosys.tec.persist.controller.AbstractPersistenceEnabledController;
import bancosys.tec.persist.uniquevalue.dao.UniqueValueReferenceDAO;
import bancosys.tec.persist.uniquevalue.domain.UniqueValueReference;
import bancosys.tec.rtm.impl.RtmController;
import bancosys.tec.utils.date.Clock;

/**
 * Controle principal de integração.
 * 
 * @author piercio
 */
public class HydraController extends AbstractPersistenceEnabledController implements BeanFactoryAware, Hydra {

    private ServicesController servicesController;

    private ExecutionLogController executionLogController;

    private PersistenceController persistenceController;

    private RtmController rtmController;

    private Context jmsSenderContext;

    private BeanFactory beanFactory;

    private ScriptController scriptController;

    private HydraProvider provider;

    private Clock clock;

    /**
     * @return o valor do campo serviceController
     */
    public ServicesController getServicesController() {
        return this.servicesController;
    }

    /**
     * @param serviceController o valor para o campo serviceController
     */
    public void setServicesController(ServicesController serviceController) {
        this.servicesController = serviceController;
    }

    /**
     * @return o valor do campo executionLogController
     */
    public ExecutionLogController getExecutionLogController() {
        return this.executionLogController;
    }

    /**
     * @param executionLogController o valor para o campo executionLogController
     */
    public void setExecutionLogController(ExecutionLogController executionLogController) {
        this.executionLogController = executionLogController;
    }

    /**
     * @return the persistenceController
     */
    public PersistenceController getPersistenceController() {
        return this.persistenceController;
    }

    /**
     * @param persistenceController the persistenceController to set
     */
    public void setPersistenceController(PersistenceController persistenceController) {
        this.persistenceController = persistenceController;
    }

    /**
     * @return instância de {@link RtmController}.
     */
    public RtmController getRtmController() {
        return this.rtmController;
    }

    /**
     * @param rtmController instância de {@link RtmController}.
     */
    public void setRtmController(RtmController rtmController) {
        this.rtmController = rtmController;
    }

    /**
     * {@inheritDoc}
     */
    public HydraRequest send(Object source, String activation) {
        return new RequestHandler(this).send(source, activation);
    }

    /**
     * {@inheritDoc}
     */
    public HydraRequest send(Object source, HydraSpecification specification) {
        return new RequestHandler(this).send(source, specification);
    }

    /**
     * {@inheritDoc}
     */
    public HydraRequest receive(HydraSystem system, InputStream input, Map<String, String> messageProperties) {
        return new RequestHandler(this).receive(system, input, messageProperties);
    }

    /**
     * Cria a identificação da mensagem.
     * 
     * @return a identificação da mensagem.
     */
    public String createIdentification() {
        UniqueValueReferenceDAO uvrDAO = this.getDAOFactory().getDAOByClass(UniqueValueReferenceDAO.class);
        UniqueValueReference uvr = uvrDAO.findBySystemIdentifier(HydraUniqueValueEnum.HYDRA);
        StringBuilder sb = new StringBuilder();
        sb.append(uvr.transactedNextValue());
        return sb.toString();
    }

    /**
     * @return the jmsSenderContext
     */
    public Context getJmsSenderContext() {
        if (this.jmsSenderContext == null) {
            this.jmsSenderContext = (Context) this.beanFactory.getBean("jmsJndiContext");
        }
        return this.jmsSenderContext;
    }

    /**
     * @param jmsSenderContext the jmsSenderContext to set
     */
    public void setJmsSenderContext(Context jmsSenderContext) {
        this.jmsSenderContext = jmsSenderContext;
    }

    /**
     * @return the scriptController
     */
    public ScriptController getScriptController() {
        return this.scriptController;
    }

    /**
     * @param scriptController the scriptController to set
     */
    public void setScriptController(ScriptController scriptController) {
        this.scriptController = scriptController;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
     */
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    /**
     * @return the provider
     */
    public HydraProvider getProvider() {
        return this.provider;
    }

    /**
     * @param provider the provider to set
     */
    public void setProvider(HydraProvider provider) {
        this.provider = provider;
    }

    /**
     * @return the clock
     */
    public Clock getClock() {
        return this.clock;
    }

    /**
     * @param clock the clock to set
     */
    public void setClock(Clock clock) {
        this.clock = clock;
    }

}